Skip to content

Per-tab projects, «Zuletzt geschlossen», new-version notice - #28

Merged
cedricvogel-leo merged 2 commits into
mainfrom
feature/tab-projects
Oct 30, 2026
Merged

cedricvogel-leo merged 2 commits into
mainfrom
feature/tab-projects

Conversation

@cedricvogel-leo

Copy link
Copy Markdown
Collaborator

P25 decision 1 (lean variant, address variant 3) and the «Neue Version verfügbar» notice. IDE PR 1 of 2; PR 2 brings libraries by URL and the notes for broken and long links.

The bump to glpython-editor v0.1.20 (the Monaco setting, glpython-edu/glpython-editor#42) follows as a commit on this branch once the tag exists. Nothing in this PR depends on it.

Behaviour

  • One project per browser tab.
    • A share link starts a new tab project and never replaces another tab's work.
    • The address bar then shows only https://glpython-edu.github.io/, as in WebTigerPython.
  • The tab's id is kept in session storage and history.state, never in the address.
    • Reload: both survive.
    • iPad Safari rebuilding an unloaded tab: history.state survives (your diagnostic, iPadOS 26.6.1).
    • Quitting Safari: neither survives, so the rescue offer below appears.
  • Projects are kept in local storage, one entry per tab. Nothing is deleted when a tab goes away: a page can't tell a close from Safari unloading it.
  • Unsaved means changed since the last «Teilen» or «Projekt herunterladen». A link's project and the untouched starter count as saved.
  • Closing or reloading with unsaved changes: the browser's own question (its own text). Desktop browsers only; iPad Safari never asks.
  • ⋮ «Zuletzt geschlossen» lists projects no open tab holds, from the last 14 days, most recent first, without untouched starters.
    • «Öffnen» opens one in this tab if it holds only the untouched starter, else in a new tab.
    • «Entfernen» deletes it. Projects older than 14 days are removed.
  • Rescue offer: a new tab without a link offers the last project changed within 24 hours right away. «Alle anzeigen» appears if there are several; ✕ closes the offer. (You wrote «in the last hours»; I chose 24 h so a Safari or iPad restart overnight is still covered. Easy to change.)
  • ⋮ «Neues Projekt» replaces «Lokales Projekt löschen» (and its «Entwicklerwerkzeuge» group). It gives the tab the starter. Opening a folder or a ZIP gives the tab that project. In both cases the previous project goes to «Zuletzt geschlossen»; nothing is deleted.
  • A duplicated tab (same id as an open one) takes its own copy. Open tabs answer each other over a BroadcastChannel.
  • Migration: today's single stored project becomes the first tab's project, once. It counts as unsaved.
  • New version:
    • The build writes version.json (the commit).
    • An open tab checks it when it comes back into view and every 30 minutes.
    • On a difference: «Neue Version verfügbar.» with «Neu laden». The code survives the reload; Python's session doesn't.

New wording, please review

Where de en
⋮ Neues Projekt New project
⋮, dialog title Zuletzt geschlossen Recently closed
dialog Projekte aus geschlossenen Tabs, 14 Tage lang in diesem Browser gespeichert. Projects of closed tabs, kept in this browser for 14 days.
dialog, empty Keine geschlossenen Projekte aus den letzten 14 Tagen. No projects closed in the last 14 days.
dialog, per project auswerter.py · Auswerter · vor 2 Stunden · «Öffnen» · 🗑 «auswerter.py entfernen» … · «Open» · «Remove auswerter.py»
offer Zuletzt bearbeitet: auswerter.py (vor 2 Stunden). · «Öffnen» · «Alle anzeigen» · ✕ «Schliessen» Last edited: auswerter.py (2 hours ago). · «Open» · «Show all» · ✕ «Close»
under a minute gerade eben just now
update notice Neue Version verfügbar. · «Neu laden» A new version is available. · «Reload»

Times come from Intl.RelativeTimeFormat («vor 5 Minuten», «gestern», «vor 3 Tagen»). Notices use the info colours (--glp-info).

Checked (Chrome against the production build, vite preview)

# Case Result
0 Fresh profile with an old single project taken over; old key removed
1 Evaluator link in tab A address is the bare /; id in session storage and history.state
2 Bare IDE in tab B starter; no offer (A is open)
3 The same link again in tab C scaffold; A keeps its work
4 Reload of A with unsaved work one question; work kept
5 A with session storage cleared, then reload (the iPad unload case) work kept
6 Duplicate of A shows A's work with its own id; editing it leaves A unchanged
7 Closing A with unsaved work question; after «Teilen», no question
8 Bare IDE after closing «Zuletzt bearbeitet: auswerter.py (gerade eben).»; «Öffnen» opens it in place
9–10 «Neues Projekt» in C starter; C's project in «Zuletzt geschlossen»
11 A different version.json, then the tab comes into view «Neue Version verfügbar.»

Build and lint pass (lint: only the existing warnings in public/coi-serviceworker.js).

Headless Chrome doesn't close a tab after a cancelled close, even on a blank test page, so «closes after Teilen» needs your manual test.

Your tests

  • Desktop Chrome:
    • Two links in two tabs stay independent.
    • Reload keeps the code.
    • Closing with changes asks; after «Teilen» or «Herunterladen» it doesn't.
    • ⋮ «Zuletzt geschlossen»: open, remove.
  • iPad:
    • Edit, force an unload with the storage-check page's «Belastungsseite», return: the code is there.
    • Quit Safari and open the IDE: the «Zuletzt bearbeitet» offer, «Öffnen».
    • Close the tab and open the IDE again: the offer.
  • After the merge: keep an IDE tab open on the iPad. After the next IDE deploy, return to it: «Neue Version verfügbar.»

Merging deploys the IDE.

🤖 Generated with Claude Code

Each browser tab has its own project, as in WebTigerPython: a share link
starts a new tab project and never replaces another tab's work, and the
address bar shows only the start page.

- The tab's id is in sessionStorage and history.state, never in the
  address. A reload keeps both; when iPad Safari rebuilds an unloaded tab,
  history.state survives (storage-check page, iPadOS 26.6.1).
- Projects are in localStorage, one entry per tab. Nothing is deleted when
  a tab goes away (a page can't tell a close from Safari unloading it).
  Open tabs answer over a BroadcastChannel: a duplicated tab takes its own
  copy, and ⋮ «Zuletzt geschlossen» lists the projects no open tab holds,
  for 14 days. A fresh tab offers the last one changed within a day
  right away - after quitting Safari or restarting the iPad a tab comes
  back empty.
- Closing or reloading with changes since the last «Teilen» or
  «Projekt herunterladen»: the browser's own question (not on an iPad).
- ⋮ «Neues Projekt» replaces «Lokales Projekt löschen»; it and opening a
  folder or ZIP start a new tab project, the old one goes to the list.
- The IDE's former single project becomes the first tab's project, once.
- The build writes version.json (the commit); an open tab checks it when it
  comes back into view and every 30 minutes, and offers «Neu laden».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cedricvogel-leo
cedricvogel-leo merged commit 0992bfb into main Oct 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant